package dd.prog2.exercises.set06;

/*
 * Ein Train-Objekt speichert „seine“ Lokomotive, aber nicht die Wagen.
 * Diese können, einer nach dem anderen, auf dem Weg über die Lokomotive erreicht werden.
 */
public class Train {
	Locomotive head;

	public Train(Locomotive loc) {
		this.head = loc;
	}

	/* Prüft, ob der Zug über mehr als nur eine Lokomotive verfügt. */
	public boolean hasCars() {
		if (this.head.getFirst() == null)
			return false;
		else
			return true;
	}

	/*
	 * hängt in den Zug einen gegebenen Wagen an der spezifizierten
	 * Index-Position ein (Index 0 bedeutet direkt hinter der Lokomotive).
	 */
	public void add(Car c, int i) {
		if(i == 0){//add as first
			c.setNext(this.head.getFirst());
			this.head.setFirst(c);
		} else {
			int j = 0;
			Car next = this.head.getFirst();
			while (j++ < i && next.getNext() != null){//add new car to position "i" or set as last
				next = next.getNext();
			}
			next.setNext(c);
		}
	}

	/* liefert die gesamte Passagierkapazität des Zuges. */
	public int getPassengers() {
		int cap = 0;
		Car next = this.head.getFirst();
		while (next != null){
			cap += next.getCapacity();
			next = next.getNext();
		}
		return cap;
	}

	/* liefert die Länge des Zuges in Metern. */
	public int getLength() {
		int length = 0;
		int cnt = 0;
		Car next = this.head.getFirst();
		while (next != null && cnt++<20){
			length += next.getLength();
			next = next.getNext();
		}
		return length;
	}

	/*
	 * hängt den ersten Wagen aus dem Zug aus und liefert den ausgehängten Wagen
	 * als Ergebnis zurück. Die restlichen Wagen bleiben am Zug. Falls es keinen
	 * Wagen gibt, wird null zurückgegeben.
	 */
	public Car removeFirst() {
		Car c = null;
		if (this.hasCars()){
			c = this.head.getFirst();
			this.head.setFirst(this.head.getFirst().getNext());
		}
		return c;
	}

	/*
	 * akzeptiert als Parameter einen anderen Zug und hängt alle Wagen des
	 * anderen Zuges in diesen Zug um. Im anderen Zug bleibt nur die Lokomotive
	 * zurück. Nutzen Sie für diese Methode geschickt die vorher definierten.
	 * Die Methode soll möglichst effizient sein.
	 */
	public void relink(Train t) {
		if(t.hasCars()){// only if t has cars
			Car thisNext = this.head.getFirst();
			Car tNext = t.head.getFirst();
			while(thisNext.getNext() != null)
					thisNext = thisNext.getNext();// get last car in this train
			thisNext.setNext(tNext);
			t.head.setFirst(null);
		} else
			System.out.println("Train has no Cars");
	}

	/*
	 * dreht die Abfolge der Wagen in diesem Zug um, das heißt, der vorher
	 * letzte Wagen wird zum ersten, und umgekehrt. Auch diese Aufgabe lässt
	 * sich effizient ohne Zwischenspeicherung des Zuges lösen!
	 */
	public void revert() {
		if(this.hasCars()){
			Car next = this.head.getFirst().getNext();// save next car
			this.head.getFirst().setNext(null);
			do {
				Car tmp = next.getNext();//temp pointer
				this.add(next, 0);//set first
				next = tmp;
			} while (next != null);
		} else {
			System.out.println("Has no Cars");
		}
	}

	@Override
	public String toString() {
		String res = "Locomotive: ";
		res += this.head.getType()+". "+this.head.getLength()+" m";
		res += "\nTrain Length: "+this.getLength();
		res += "\nCapacity: "+this.getPassengers();
		res += this.carsList();
		return res;
	}

	public String carsList(){
		String res = "";
		Car next = this.head.getFirst();
		while(next != null){
			res += next.getCarNr()+"("+next.getLength()+", "+next.getCapacity()+") ";
			next = next.getNext();
		}
		return "\nCars List: "+res;
	}
}
